﻿using Microsoft.Extensions.Options;
using StackExchange.Redis;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;

namespace Singer.Middleware.Redis
{
    public class RedisConnectionPool : IRedisConnectionPool
    {
        RedisOptions Options;
        ConcurrentDictionary<string, IConnectionMultiplexer> ConnectionPool = new ConcurrentDictionary<string, IConnectionMultiplexer>();
        public RedisConnectionPool(IOptions<RedisOptions> options)
        {
            Options = options.Value;
        }

        public IConnectionMultiplexer GetConnection(string connectionName)
        {
            return Init(connectionName);
        }

        public IDatabase GetDatabase(int db = -1, string? connectionName = null)
        {
            var conn = Init(connectionName);
            return conn.GetDatabase(db);
        }

        private IConnectionMultiplexer Init(string? connectionName = null)
        {
            if (string.IsNullOrWhiteSpace(connectionName))
                connectionName = RedisOptions.DefaultName;
            var connectionString = Options.Get(connectionName);
            ConfigurationOptions opts = ConfigurationOptions.Parse(connectionString);
            if (!string.IsNullOrWhiteSpace(Options.InstanceName))
                opts.ChannelPrefix = Options.InstanceName.TrimEnd(':') + ":";
            IConnectionMultiplexer connection = ConnectionMultiplexer.Connect(opts);
            if (connection == null)
                throw new Exception($"【Redis】The '{connectionName}' connection failed.");
            var conn = ConnectionPool.GetOrAdd(connectionName, connection);
            return conn;
        }

        public void Dispose()
        {
            foreach (var connection in ConnectionPool)
            {
                connection.Value.Dispose();
            }
            ConnectionPool.Clear();
        }
    }
}
